package wortubung.core;

import wortubung.inflection.Decliner;
import wortubung.inflection.VerbConjugation;

public class POSInfo {
	private POS pos;

	private static class WithDecliner extends POSInfo {
		Decliner decliner;

		WithDecliner(POS pos, Decliner decliner) {
			super(pos);
			this.decliner = decliner;
		}

		@Override public Decliner getDecliner() { return decliner; }
	}

	private static class NounInfo extends WithDecliner {
		NounCategory nounCategory;
		
		NounInfo(POS pos, NounCategory nounCat, Decliner decliner) {
			super(pos, decliner);
			this.nounCategory = nounCat;
		}

		@Override public NounCategory getNounCategory() { return nounCategory; }
	}

	private static class VerbInfo extends POSInfo {
		VerbConjugation conjugator;

		VerbInfo(POS pos, VerbConjugation conjugator) {
			super(pos);
			this.conjugator = conjugator;
		}

		@Override public VerbConjugation getConjugation() { return conjugator; }
	}

	public POSInfo(POS pos) { this.pos = pos; }

	public POS getPOS() { return pos; }
	public POSCategory getCategory() { return pos.getCategory(); }
	public String toDisplay(boolean full) { return full ? toString() : pos.getShortName(); }
	public boolean isNoun() { return getPOS().isNoun(); }
	public boolean isVerb() { return getPOS().isVerb(); }

	// For nouns
	public String getShortName() { return getPOS().getShortName(); }
	public NounCategory getNounCategory() { return null; }
	public GENDER getGender() { return getPOS().getGender(); }

	// For declinables (nouns, adjectives, pronouns, articles, etc.)
	public Decliner getDecliner() { return null; }

	// For verbs
	public boolean isReflexiveVerb() { return pos.isReflexiveVerb(); }
	public VerbConjugation getConjugation() { return null; }

	// Convert to words with special declension
    public POSInfo toDeclinable(Decliner decliner) {
    	if (decliner == null)
    		return this;
    	if (this instanceof WithDecliner) {
    		WithDecliner wd = (WithDecliner)this;
    		wd.decliner = decliner;
    		return wd;
    	}
    	if (isNoun())
    		return new NounInfo(pos, getNounCategory(), decliner);
    	return new WithDecliner(pos, decliner);
    }

    // Convert to verb with special conjugation
    public POSInfo toVerb(VerbConjugation conjugator) {
    	if (conjugator == null)
    		return this;
    	return new VerbInfo(pos, conjugator);
    }

    public String toString() {
		String ret = pos.getShortName();
		NounCategory nounCat = getNounCategory();
		if (nounCat != NounCategory.NONE)
			return ret + "." + nounCat;
		return ret;
	}
    
    public static POSInfo parsePOS(String posStr) {
    	String[] sa = posStr.split("\\.");
    	POS pos = POS.fromShortName(sa[0]);
    	NounCategory nc = null;
    	if (sa.length > 1 && pos.isNoun()) {
    		nc = NounCategory.from(sa[1]);
    		return new NounInfo(pos, nc, null);
    	}
   		return new POSInfo(pos);
    }
}
